/*************************************************************************
	> File Name: 002.CircularQueue.c
	> Author: Maureen 
	> Mail: Maureen@qq.com 
	> Created Time: 五  9/ 3 10:39:08 2021
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define COLOR(a, b) "\033[;" #b "m" a "\033[0m"
#define RED(a) COLOR(a, 31)

typedef struct Queue {
    int *data;
    int head;
    int tail;
    int count; //记录队列中已经存储的元素个数
    int capacity;
} Queue;

/*
 * 队列的初始化
 */
Queue *init(int n) {
    Queue *que = (Queue *)malloc(sizeof(Queue));
    que->data = (int *)malloc(sizeof(int) * n);
    que->head = 0;
    que->tail = 0;
    que->count = 0;
    que->capacity = n;
    return que;
}

/*
 * 返回队首元素
 */
int front(Queue *que) {
    return que->data[que->head];
}

/*
 * 判断队列是否为空
 */
int empty(Queue *que) {
    return que->count == 0;
}

/*
 * 入队
 */
int push(Queue *que, int val) {
    if (que == NULL) return -1;
    if (que->count == que->capacity) {
        printf(RED("Queue is full!")"\n");
        return -1;
    }
    que->data[que->tail++] = val;
    if (que->tail == que->capacity) que->tail = 0;
    que->count++;
    return 0;
}

/*
 * 出队
 */
int pop(Queue *que) {
    if (que == NULL) return -1;
    if (empty(que)) return -1;
    que->head++;
    if (que->head == que->capacity) que->head = 0;
    que->count--;
    return 0;
}

/*
 * 队列元素的打印
 */
void output(Queue *que) {
    printf("Queue : [");
    for (int i = que->head, j = 0; j < que->count; j++, i++) {
        j && printf(", ");
        printf("%d", que->data[i % que->capacity]);
    }
    printf("]\n");
    return ;
}

/*
 * 队列的销毁
 */
void clear(Queue *que) {
    if (que == NULL) return ;
    free(que->data);
    free(que);
    return ;
}

int main() {
    srand(time(0));
    #define max_op 20 
    Queue *que = init(max_op / 2);
    for (int i = 0; i < max_op; i++) {
        int val = rand() % 100;
        int op = rand() % 4;
        switch (op) {
            case 0:
            case 1:
            case 2: {
                printf("push %d to the Queue, result = %d\n", val, push(que, val));
            } break;
            case 3: {
                printf("pop %d from the Queue, result = %d\n", front(que), pop(que));
            } break;
        }
        output(que), printf("\n");
    }
    #undef max_op 
    clear(que);

    return 0;
}
